package com.rw.coco.expression.parser.element;

import com.rw.coco.expression.parser.element.enumeration.Df;
import com.rw.coco.handler.message.reply.handler.command.exception.global.NumberOverflowException;
import com.rw.tool.util.expression.element.ExpressionElement;
import com.rw.tool.util.expression.element.NumberElement;
import com.rw.tool.util.random.RandomUtil;
import com.rw.tool.util.string.StringUtil;
import lombok.Getter;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

@Getter
public class RfNumberElement extends NumberElement implements DiceNumberElement {
    public static final String REGEX = "(\\d*)d?f";

    private static final Pattern DICE_PATTERN = Pattern.compile("^" + REGEX + "$", Pattern.CASE_INSENSITIVE);

    // 展开展示转缩写的限额，骰子数超过这个数则转缩写
    private static final int ABBR_FACTOR = 30;

    private final int count;

    private final List<Df> resultList;

    private final int sum;

    public RfNumberElement(int count) {
        super(new BigDecimal(0));

        this.count = count;
        this.resultList = new ArrayList<>(count);

        for (int i = 0; i < count; i++) {
            int dfNum = RandomUtil.nextInt(Df.values().length);
            resultList.add(Df.values()[dfNum]);
        }

        this.sum = resultList.stream().mapToInt(Df::weight).sum();
    }

    /**
     * 转为骰子表达式，例如 '1d3'
     */
    @Override
    public String toDiceString() {
        return count + "DF";
    }

    /**
     * 转化为计算结果表达式，例如 '1+3'
     */
    @Override
    public String toAfterDiceString(boolean simple) {
        if (count > ABBR_FACTOR || simple) {
            return String.valueOf(sum);
        }

        String rfExpression = resultList.stream()
                .map(Df::getDiceStr)
                .collect(Collectors.joining(" "));

        return "[" + rfExpression + "]";
    }

    /**
     * 转化为计算结果表达式并加入括号，例如 '(1+3)'
     * 如果数字只有一个，则不加括号
     */
    @Override
    public String afterDiceWithCast(boolean simple) {
        return toAfterDiceString(simple);
    }

    @Override
    public BigDecimal getNumber() {
        return new BigDecimal(sum);
    }

    @Override
    public String toString() {
        return String.valueOf(sum);
    }

    public static ExpressionElement parse(String parseStr) {
        // 匹配正则表达式
        Matcher matcher = DICE_PATTERN.matcher(parseStr);
        if (!matcher.find()) {
            return null;
        }

        // 默认四个DF
        int dfCount = 4;
        String dfCountStr = matcher.group(1);
        if (!StringUtil.isBlank(dfCountStr)) {
            try {
                dfCount = Integer.parseInt(dfCountStr);
            } catch (NumberFormatException exception) {
                throw new NumberOverflowException();
            }
        }

        if (dfCount <= 0) {
            return null;
        }

        return new RfNumberElement(dfCount);
    }
}
